package io.kimmking.common.zookeeper.annotation;

import io.kimmking.common.zookeeper.zktemplate.ZookeeperTemplate;
import io.kimmking.dubbo.common.unit.ThrowableActionV2;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.zookeeper.CreateMode;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.InetAddress;

/**
 * 此处使用SpringBoot里的Aspect(AOP)进行自定义注解
 */
@Slf4j
@Aspect
@Component
public class registerZKAspect {

    @Resource
    private ZookeeperTemplate zookeeperTemplate;

    @Pointcut("@annotation(io.kimmking.common.zookeeper.annotation.registerZK)")
    private void pointcut(){}

    @Before("pointcut() && @annotation(registerZK)")
    public void before(JoinPoint joinPoint, registerZK registerZK) {
        //类名
//        String clsName = joinPoint.getSignature().getDeclaringType().getSimpleName();
        //方法名
//        String modName = joinPoint.getSignature().getName();
        //参数
//        Object[] args = joinPoint.getArgs();

        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Class<?> returnType = methodSignature.getReturnType();
        try {
            registerService(zookeeperTemplate, returnType.getName(), registerZK.rootPath(), registerZK.port());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 向ZK注册节点信息
     * @param zookeeperTemplate
     * @param service
     * @param port
     * @throws Exception
     */
    private static void registerService(ZookeeperTemplate zookeeperTemplate, String service , String rootPath, String port) throws Exception {
        ThrowableActionV2.execute(() -> {
            if (zookeeperTemplate.isExists("/" , rootPath)) {
                zookeeperTemplate.createNode("/", rootPath, CreateMode.PERSISTENT);
                //对rootPath的一级目录进行监听
                zookeeperTemplate.watchChildren(rootPath, (client, event) -> {
                    PathChildrenCacheEvent.Type type = event.getType();
                    switch (type) {
                        case INITIALIZED :
                            log.info("{} ZK子节点初始化完成", event.getData().getPath());
                        case CHILD_ADDED :
                            log.info("{} ZK子节点创建成功", event.getData().getPath());
                        case CHILD_REMOVED :
                            log.info("{} ZK子节点已删除", event.getData().getPath());
                    }
                });
            }
            zookeeperTemplate.createNode(rootPath,InetAddress.getLocalHost().getHostAddress().concat("_").concat(port), CreateMode.EPHEMERAL);
        });
    }

}